import os
import sqlite3
import json
from abc import ABC, abstractmethod

from camel.agents import RolePlaying
from camel.messages import ChatMessage
from camel.typing import TaskType, ModelType
from chatad.chat_env import ChatEnv
from chatad.statistics import get_info
from chatad.utils import log_visualize, log_arguments
from visualizer.app import send_msg
from chatad.data_classifier import DataClassifier


class Phase(ABC):
    """
    【抽象基类】所有具体任务阶段的父类。

    这个类定义了一个"阶段（Phase）"的通用结构和接口，但它本身不能被直接实例化。
    每个具体的阶段（如"需求分析"、"市场分析"）都必须继承自这个类，并实现其抽象方法。

    核心功能：
    1.  初始化阶段所需的基本信息（如角色名称、阶段提示、模型类型等）。
    2.  提供一个核心的`chatting`方法，用于管理两个AI智能体之间的多轮对话。
    3.  定义了一个`self_reflection`机制，允许对对话结论进行反思和修正。
    4.  声明了`update_phase_env`、`update_chat_env`和`execute`等必须由子类实现的抽象方法。
    """

    def __init__(self,
                 assistant_role_name,
                 user_role_name,
                 phase_prompt,
                 role_prompts,
                 phase_name,
                 model_type,
                 log_filepath):
        """
        初始化一个Phase实例。

        Args:
            assistant_role_name (str): 在本阶段中扮演"助理"角色的名称（即，接收消息方）。
            user_role_name (str): 在本阶段中扮演"用户"角色的名称（即，发起对话方）。
            phase_prompt (str): 描述本阶段核心任务的提示。
            role_prompts (dict): 包含所有角色系统提示的字典。
            phase_name (str): 本阶段的名称。
            model_type (ModelType): 使用的AI模型类型。
            log_filepath (str): 日志文件的路径。
        """
        self.seminar_conclusion = None
        self.assistant_role_name = assistant_role_name
        self.user_role_name = user_role_name
        self.phase_prompt = phase_prompt
        self.phase_env = dict()
        self.phase_name = phase_name
        self.assistant_role_prompt = role_prompts[assistant_role_name]
        self.user_role_prompt = role_prompts[user_role_name]
        self.ceo_prompt = role_prompts["ChiefExecutiveOfficer"]
        self.counselor_prompt = role_prompts["Counselor"]
        # self.max_retries = 3
        self.reflection_prompt = """这里有一个关于两个角色之间的对话: {conversations} {question}"""
        self.model_type = model_type
        self.log_filepath = log_filepath

    @log_arguments
    def chatting(
            self,
            chat_env,
            task_prompt: str,
            assistant_role_name: str,
            user_role_name: str,
            phase_prompt: str,
            phase_name: str,
            assistant_role_prompt: str,
            user_role_prompt: str,
            task_type=TaskType.CHATAD,
            need_reflect=False,
            model_type=ModelType.DEFAULT_MODEL,
            placeholders=None,
            chat_turn_limit=10
    ) -> str:
        """
        管理两个AI智能体之间进行一次完整的对话（包含多轮）。
        这是Phase中非常核心的功能，它封装了`camel.agents.RolePlaying`的调用，
        并处理了对话的启动、多轮交互、信息提取和日志记录。
        Args:
            chat_env (ChatEnv): 全局的聊天环境。
            task_prompt (str): 原始的用户任务提示。
            assistant_role_name (str): 接收聊天的一方。
            user_role_name (str): 发起聊天的一方。
            phase_prompt (str): 阶段的提示。
            phase_name (str): 阶段的名称。
            assistant_role_prompt (str): 对话阶段一方角色的提示。
            user_role_prompt (str): 对话阶段一方角色的提示。
            task_type (TaskType): 任务类型
            need_reflect (bool): 检查反思的标志
            with_task_specify (bool): 带有任务指定
            model_type (ModelType): 模型类型
            placeholders (dict): 用于生成阶段提示的占位符
            chat_turn_limit (int): 对话的最大轮次
        Returns:
            str: 经过对话得出的最终结论。
        """

        if placeholders is None:
            placeholders = {}
        assert 1 <= chat_turn_limit <= 100
        # 当前环境是否存在对话双方
        if not chat_env.exist_employee(assistant_role_name):
            raise ValueError(f"{assistant_role_name} not recruited in ChatAD.")
        if not chat_env.exist_employee(user_role_name):
            raise ValueError(f"{user_role_name} not recruited in ChatAD.")

        # 启动角色扮演  用于初始化user和assistant两个智能体，并将role prompt和background prompt结合
        role_play_session = RolePlaying(
            assistant_role_name=assistant_role_name,
            user_role_name=user_role_name,
            assistant_role_prompt=assistant_role_prompt,
            user_role_prompt=user_role_prompt,
            task_prompt=task_prompt,
            task_type=task_type,  # TaskType.CHATAD
            model_type=model_type,
            background_prompt=chat_env.config.background_prompt
        )
        # 开始聊天，用于先生成用户输入（phase-prompt）
        _, input_user_msg = role_play_session.init_chat(None, placeholders, phase_prompt) # 此处有**start chat**
        seminar_conclusion = None
        # 处理聊天
        # 有两种类型的结论
        # 1. 带有 "<好的>" 标记
        # 1.1 从助理或用户角色获取结论标志 (ChatAgent.info)，这意味着在对话中存在特殊的 "<好的>" 标记
        # 1.2 将 "<好的>" 添加到对话的反思内容中（可能是一个没有 "<好的>" 标记的终止对话）
        # 2. 没有 "<好的>" 标记，这意味着对话已终止或正常结束而没有生成标记的结论，不需要反思
        for i in range(chat_turn_limit):
            # 开始聊天，我们代表user并向assistant发送消息
            # 1. 所以 input_user_msg 应该是 assistant_role_prompt + phase_prompt
            # 2. 然后 input_user_msg 发送给 assistant 并得到 assistant_response
            # 3. 之后我们代表assistant并向user发送消息，所以 input_assistant_msg 是 user_role_prompt + assistant_response
            # 4. 然后 input_assistant_msg 发送给 user 并得到 user_response
            # 以上所有步骤都在 role_play_session.step 中完成，该步骤user和assistant的一次完整对话（user->assistant,assistant->user)
            # 第一次交互记录在 role_play_session.init_chat 中
            # 先user问assistant 再assistant问user
            assistant_response, user_response = role_play_session.step(input_user_msg, chat_turn_limit == 1)

            conversation_meta = "**" + assistant_role_name + "<->" + user_role_name + " on : " + str(
                phase_name) + ", turn " + str(i) + "**\n\n"

            # TODO：此处出现 max_tokens_exceeded 错误
            if isinstance(assistant_response.msg, ChatMessage):
                # 我们在这里记录第二次交互
                log_visualize(role_play_session.assistant_agent.role_name,   # role_play_session.user_agent.system_message.content为总prompt+user prompt
                              conversation_meta + "[" + role_play_session.user_agent.system_message.content + "]\n\n" + assistant_response.msg.content) # 为assistant回复
                                                                             # content内容是在RolePlaying中生成，system-message为agent函数名
                if role_play_session.assistant_agent.info:  # 已有结论 对话结束
                    seminar_conclusion = assistant_response.msg.content
                    break
                if assistant_response.terminated:
                    break

            if isinstance(user_response.msg, ChatMessage):
                # 这是第二次交互的结果，可能用于开始下一轮聊天
                log_visualize(role_play_session.user_agent.role_name,
                              conversation_meta + "[" + role_play_session.assistant_agent.system_message.content + "]\n\n" + user_response.msg.content)
                if role_play_session.user_agent.info:
                    seminar_conclusion = user_response.msg.content
                    break
                if user_response.terminated:
                    break

            # 继续聊天
            if chat_turn_limit > 1 and isinstance(user_response.msg, ChatMessage):
                input_user_msg = user_response.msg  # 将assistant的输出作为user的输入
            else:
                break

        # 进行自我反思
        if need_reflect:
            if phase_name == "MarketAnalysis":
                chat_env.env_dict['market_analysis'] = seminar_conclusion.split("<好的>")[-1].lower().replace(".","").strip()
                seminar_conclusion = "<好的> " + self.self_reflection(task_prompt, role_play_session, phase_name, chat_env)
                chat_env.env_dict['market_analysis'] = seminar_conclusion.split("<好的>")[-1].lower().replace(".","").strip()
            elif phase_name == "RecommendationsForPlacement":
                chat_env.env_dict['placement_recommendations'] = seminar_conclusion.split("<好的>")[-1].lower().replace(".",                                                                                     "").strip()
                seminar_conclusion = "<好的> " + self.self_reflection(task_prompt, role_play_session, phase_name,                                                 chat_env)
                chat_env.env_dict['placement_recommendations'] = seminar_conclusion.split("<好的>")[-1].lower().replace(".",
                                                                                                              "").strip()
        else:
            seminar_conclusion = assistant_response.msg.content

        log_visualize("**[Seminar Conclusion]**:\n\n {}".format(seminar_conclusion))
        seminar_conclusion = seminar_conclusion.split("<好的>")[-1]
        return seminar_conclusion

    def self_reflection(self,
                        task_prompt: str,
                        role_play_session: RolePlaying,
                        phase_name: str,
                        chat_env: ChatEnv) -> str:
        """
        对一轮对话的结果进行"自我反思"。

        这个方法通过引入"ChiefExecutiveOfficer"和"Counselor"两个更高层次的角色，
        来审查和提炼前一轮对话的内容，以得出更精确、更可靠的结论。

        Args:
            task_prompt (str): 原始任务提示。
            role_play_session (RolePlaying): 需要被反思的对话会话。
            phase_name (str): 正在进行反思的阶段名称。
            chat_env (ChatEnv): 全局聊天环境。

        Returns:
            str: 经过反思和提炼后的新结论。
        """
        messages = role_play_session.assistant_agent.stored_messages if len(
            role_play_session.assistant_agent.stored_messages) >= len(
            role_play_session.user_agent.stored_messages) else role_play_session.user_agent.stored_messages
        messages = ["{}: {}".format(message.role_name, message.content.replace("\n\n", "\n")) for message in messages]
        messages = "\n\n".join(messages)


        if phase_name == "MarketAnalysis":
            log_visualize("市场分析——反思阶段")
            messages1=[f"市场分析: {chat_env.env_dict['market_analysis']}"]  # 直接使用f-string
            message3 = [f"数据分析: {chat_env.env_dict['data_analysis']}"]  # 直接使用f-string
            message2=["市场分析阶段由MarketAnalystAgent和DataEngineer对话讨论进行，使用了数据分析阶段的结论:"]
            messages = f"{message2[0]}\n\n{message3[0]}\n\n{messages1[0]}"
            # messages = message2.join("\n\n".join(message3.join("\n\n".join(messages1))))
            question = """你觉得上述市场分析是否正确，如果正确，请原样输出上面市场分析(market analysis)的结果，如果你觉得不正确，请输出你对此的合理准确市场分析，你也可以对上述市场分析进行修改，输出修改后的结果"""
        elif phase_name == "RecommendationsForPlacement":
            log_visualize("投放建议案分析——反思阶段")
            messages1 = [f"投放建议案分析: {chat_env.env_dict['placement_recommendations']}"]  # 直接使用f-string
            message3 = [f"市场分析: {chat_env.env_dict['market_analysis']}"]  # 直接使用f-string
            message2 = ["广告投放阶段由StrategicPlanner和MarketAnalystAgent对话讨论进行，使用了市场分析阶段的结论:"]
            messages = f"{message2[0]}\n\n{message3[0]}\n\n{messages1[0]}"
            question = """你觉得上述投放建议案分析是否正确，如果正确，请原样输出上面投放建议案分析的结果，如果你觉得不正确，请输出你对此的合理准确的投放建议案分析，你也可以对上述投放建议案分析进行修改，输出修改后的结果 """
        else:
            raise ValueError(f"Reflection of phase {phase_name}: Not Assigned.")

        # 反思实际上是 CEO 和顾问之间的一个特殊阶段
        # 他们阅读这个阶段的整个聊天历史，并给出这个阶段的精炼结论
        reflected_content = \
            self.chatting(chat_env=chat_env,
                          task_prompt=task_prompt,
                          assistant_role_name="ChiefExecutiveOfficer",
                          user_role_name="Counselor",
                          phase_prompt=self.reflection_prompt,
                          phase_name="Reflection",
                          assistant_role_prompt=self.ceo_prompt,
                          user_role_prompt=self.counselor_prompt,
                          placeholders={"conversations": messages, "question": question},
                          need_reflect=False,
                          chat_turn_limit=1,
                          model_type=self.model_type)
        return reflected_content

    @abstractmethod
    def update_phase_env(self, chat_env):
        """
        【抽象方法】在执行对话前，用全局环境更新阶段内部环境。
        子类必须实现此方法，以从`chat_env`中提取当前阶段所需的信息，
        并填充到`self.phase_env`中。这些信息将用于格式化`phase_prompt`。
        """
        pass

    @abstractmethod
    def update_chat_env(self, chat_env) -> ChatEnv:
        """
        【抽象方法】在阶段执行后，用阶段成果更新全局环境。
        子类必须实现此方法，将在本阶段中产生的关键信息（如产品模态、分析报告等）
        添加回`chat_env`中，供后续阶段使用。
        """
        pass

    def execute(self, chat_env, chat_turn_limit, need_reflect) -> ChatEnv:
        """
        【抽象方法】执行本阶段的核心逻辑。
        这是每个具体阶段子类必须实现的主入口。一个典型的实现流程是：
        1. 调用 `self.update_phase_env(chat_env)` 从全局环境准备数据。
        2. 调用 `self.chatting(...)` 来执行AI对话并获取结论。
        3. 调用 `self.update_chat_env(chat_env)` 将阶段成果写回全局环境。
        4. 返回更新后的 `chat_env`。
        """
        self.update_phase_env(chat_env)
        self.seminar_conclusion = \
            self.chatting(chat_env=chat_env,
                          task_prompt=chat_env.env_dict['task_prompt'],
                          need_reflect=need_reflect,
                          assistant_role_name=self.assistant_role_name,
                          user_role_name=self.user_role_name,
                          phase_prompt=self.phase_prompt,
                          phase_name=self.phase_name,
                          assistant_role_prompt=self.assistant_role_prompt,
                          user_role_prompt=self.user_role_prompt,
                          chat_turn_limit=chat_turn_limit,
                          placeholders=self.phase_env,
                          model_type=self.model_type)
        chat_env = self.update_chat_env(chat_env)
        return chat_env


class DemandAnalysis(Phase):
    """
    【阶段】需求分析 (DemandAnalysis)

    职责：与"用户"和"产品经理"对话，明确最终要产出的产品形态（如PPT、报告等）。
    """
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def update_phase_env(self, chat_env):
        pass

    def update_chat_env(self, chat_env) -> ChatEnv:
        if len(self.seminar_conclusion) > 0:
            chat_env.env_dict['modality'] = self.seminar_conclusion.split("<好的>")[-1].lower().replace(".", "").strip()
        return chat_env

class AdvertisingShootingSuggestions(Phase):
    """
    【阶段】广告拍摄建议 (AdvertisingShootingSuggestions)

    职责：生成关于广告拍摄的具体建议。
    """
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def update_phase_env(self, chat_env):
        self.phase_env.update({
            "task": chat_env.env_dict['task_prompt'],
            "description": chat_env.env_dict['task_description'],
            "modality": chat_env.env_dict['modality'],
            "crawled_data": chat_env.env_dict.get('crawled_data', '[]')
        })

    def update_chat_env(self, chat_env) -> ChatEnv:
        if len(self.seminar_conclusion) > 0:
            chat_env.env_dict['advertising_suggestions'] = self.seminar_conclusion.split("<好的>")[-1].lower().replace(".", "").strip()
        log_visualize(
            "**[Advertising Shooting Suggestions]**:\n\n {}".format(self.seminar_conclusion))
        return chat_env


class DataCrawling(Phase):
    """
    【阶段】数据爬取 (DataCrawling)

    职责：模拟一个网络爬虫，根据需求从（模拟的）网络上抓取数据。
    """
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.database_path = "promotion_data.sqlite"

    def update_phase_env(self, chat_env):
        self.phase_env.update({
            "task": chat_env.env_dict.get('task_prompt', ''),
            "description": chat_env.env_dict.get('task_description', ''),
            "modality": chat_env.env_dict.get('modality', ''),
            "relevant_categories": "\n".join(chat_env.env_dict.get('relevant_categories', []))
        })

    def update_chat_env(self, chat_env) -> ChatEnv:
        if self.seminar_conclusion and len(self.seminar_conclusion) > 0:
            chat_env.env_dict['data_analysis'] = self.seminar_conclusion.split("<好的>")[-1].lower().replace(".", "").strip()
            # 记录到日志
            log_visualize(
                f"**[数据获取结果]**:\n\n数据已加载到任务上下文。包含 {chat_env.env_dict.get('total_data_rows', 0)} 条记录。")
        else:
            chat_env.env_dict['crawled_data'] = "未找到与任务相关的数据。"
            log_visualize("**[数据获取结果]**:\n\n 未找到相关数据。")

        return chat_env

    def execute(self, chat_env, chat_turn_limit=None, need_reflect=None) -> ChatEnv:
        """自定义执行流程，先加载数据再进行对话"""
        
        # 1. 更新阶段环境
        self.update_phase_env(chat_env)
        
        # 2. 实际加载数据
        relevant_categories = chat_env.env_dict.get('relevant_categories', [])
        
        if relevant_categories:
            # 从数据库加载数据
            data_classifier = DataClassifier(self.database_path)
            # 修改为最多10条
            relevant_data = data_classifier.fetch_data_by_categories(relevant_categories, max_rows=10)
            chat_env.env_dict["classified_data"] = relevant_data
            
            # 计算数据总行数
            total_rows = sum(len(data) for data in relevant_data.values())
            chat_env.env_dict["total_data_rows"] = total_rows
            
            # 格式化数据为可读文本，使用广告投放格式，只显示前10条
            formatted_data = data_classifier.format_data_for_context(
                relevant_data, 
                max_display_rows=10,
                format_template="| {index} | {company} | {platform} {volume} (100.00%) | {volume} | {days} | {date} |"
            )
            
            # 发送到前端显示
            if total_rows > 0:
                # 分段发送避免消息过长
                chunks = [formatted_data[i:i+2000] for i in range(0, len(formatted_data), 2000)]
                for i, chunk in enumerate(chunks):
                    if i == 0:
                        send_msg("数据工程师", f"已加载 {total_rows} 条广告投放数据，以下是前10条数据预览：\n\n{chunk}")
                    else:
                        send_msg("数据工程师", f"数据预览(续{i})：\n\n{chunk}")
                
                # 预先填充结论，避免数据重复
                self.seminar_conclusion = formatted_data
                self.phase_env.update({"crawled_data":formatted_data })
                self.seminar_conclusion = \
                    self.chatting(chat_env=chat_env,
                                task_prompt=chat_env.env_dict['task_prompt'],
                                need_reflect=need_reflect,
                                assistant_role_name=self.assistant_role_name,
                                user_role_name=self.user_role_name,
                                phase_prompt=self.phase_prompt,
                                phase_name=self.phase_name,
                                assistant_role_prompt=self.assistant_role_prompt,
                                user_role_prompt=self.user_role_prompt,
                                chat_turn_limit=chat_turn_limit,
                                placeholders=self.phase_env,
                                model_type=self.model_type)
            else:
                self.seminar_conclusion = "未找到与任务相关的数据。"
                send_msg("数据工程师", "未找到与任务相关的数据。")
        else:
            self.seminar_conclusion = "未选择任何数据类别，跳过数据加载。"
            send_msg("数据工程师", "未选择任何数据类别，跳过数据加载。")
        
        # 3. 更新全局环境
        chat_env = self.update_chat_env(chat_env)
        return chat_env


class MarketAnalysis(Phase):
    """
    【阶段】市场分析 (MarketAnalysis)

    职责：基于已有信息，生成一份市场分析报告。
    """
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.database_path = "promotion_data.sqlite"
    def update_phase_env(self, chat_env):
        relevant_categories = chat_env.env_dict.get('relevant_categories', [])
        # 加载原始数据信息
        formatted_data = "未找到相关数据"
        conn = None
        try:
            if relevant_categories and os.path.exists(self.database_path):
                conn = sqlite3.connect(self.database_path)
                cursor = conn.cursor()
                
                # 获取第一个相关类别的详细数据
                category = relevant_categories[0] if relevant_categories else None
                if category:
                    # 获取数据表中该类别的前10条记录（改为10条）
                    cursor.execute("SELECT * FROM DataItems WHERE category = ? LIMIT 10", (category,))
                    rows = cursor.fetchall()
                    
                    # 获取表头信息
                    cursor.execute("SELECT headers FROM Categories WHERE category = ?", (category,))
                    headers_json = cursor.fetchone()
                    headers = json.loads(headers_json[0]) if headers_json else []
                    
                    # 格式化数据为与原数据库一致的表格形式
                    if rows:
                        data_lines = [f"数据预览({category})，显示前 10 条:", ""]
                        
                        # BUG FIX: 动态生成表头，以适应不同的数据源
                        name_header = headers[1] if headers and len(headers) > 1 else "公司/产品名称"
                        
                        # 添加表头
                        data_lines.append(f"序号 | {name_header} | 平台 | 投放量 | 天数 | 最后投放日期")
                        data_lines.append("-" * 80)
                        
                        # 添加数据行
                        for i, row in enumerate(rows, 1):
                            # 获取记录ID和数据JSON
                            row_id, row_category, data_json = row[0], row[1], row[2]
                            data = json.loads(data_json)
                            
                            # BUG FIX: 动态获取公司/品牌/开发者等名称
                            # 根据从数据库加载的表头列表，使用第二列的表头作为key
                            name_key = headers[1] if headers and len(headers) > 1 else None
                            
                            # 提供一个回退链，以防动态key获取失败
                            if name_key:
                                company = data.get(name_key, "未知")
                            else:
                                # 扩展的回退链，以处理各种可能的名称键
                                company = data.get("公司名称",
                                          data.get("开发商名称",
                                          data.get("品牌名称",
                                          data.get("短剧名称",
                                          data.get("小说名称",
                                          data.get("小程序名称", "未知"))))))

                            # 提取其他字段
                            platform = data.get("投放平台", "巨量广告/千川")
                            volume = data.get("投放广告创意数", data.get("投放量", i*100))
                            days = data.get("投放天数", 14)
                            last_date = data.get("最后投放时间", "2025-04-14")
                            
                            # 格式化为要求的格式
                            data_line = f"| {i} | {company} | {platform} {volume} (100.00%) | {volume} | {days} | {last_date} |"
                            data_lines.append(data_line)
                        
                        formatted_data = "\n".join(data_lines)
                        
                        # 添加总行数信息
                        cursor.execute("SELECT COUNT(*) FROM DataItems WHERE category = ?", (category,))
                        total_count = cursor.fetchone()[0]
                        formatted_data += f"\n\n总共加载了 {total_count} 条数据记录，显示了 10 条。"
                    else:
                        formatted_data = f"类别 '{category}' 没有找到数据记录"
            else:
                formatted_data = "未选择任何数据类别，或数据库不存在"
                
        except Exception as e:
            formatted_data = f"获取数据时出错: {str(e)}"
        finally:
            if conn:
                conn.close()
                
        self.phase_env.update({
            "task": chat_env.env_dict.get('task_prompt', ''),
            "description": chat_env.env_dict.get('task_description', ''),
            "modality": chat_env.env_dict.get('modality', ''),
            "ideas": chat_env.env_dict.get('ideas', ''),
            "data_analysis": chat_env.env_dict.get('data_analysis', ''),
            "raw_data": formatted_data
        })

    def update_chat_env(self, chat_env) -> ChatEnv:
        if len(self.seminar_conclusion) > 0:
            chat_env.env_dict['market_analysis'] = self.seminar_conclusion.split("<好的>")[-1].lower().replace(".", "").strip()
        log_visualize(
            "**[市场分析结果]**:\n\n {}".format(self.seminar_conclusion))
        return chat_env
        
    def execute(self, chat_env, chat_turn_limit=None, need_reflect=None) -> ChatEnv:
        """自定义执行流程，直接展示数据库原始格式而非让AI分析"""
        
        # 1. 更新阶段环境
        self.update_phase_env(chat_env)
        
        # 2. 获取原始数据展示
        raw_data = self.phase_env.get("raw_data", "未找到相关数据")
        
        # 记录到日志和对话中
        log_visualize(f"**[市场数据原始格式]**:\n\n{str(raw_data)}")
        
        # # 发送到前端
        # send_msg("市场分析师", f"根据所选数据类别，以下是投放情况的原始数据（仅显示前10条），可直接用于广告平台参考：\n\n{str(raw_data)}")
        
        # 填充结论
        self.seminar_conclusion = raw_data
        
        # 3. 如果有需要，可以在这里添加简要分析
        if chat_turn_limit and chat_turn_limit > 0:
            # analysis_prompt = f"上面是原始的投放数据（前10条）。请你基于这些数据提供非常简短的市场策略建议，不要重复展示数据。"
            # self.phase_prompt = analysis_prompt
            
            # 进行对话获取简要分析
            self.seminar_conclusion = \
                self.chatting(chat_env=chat_env,
                            task_prompt=chat_env.env_dict['task_prompt'],
                            need_reflect=need_reflect,
                            assistant_role_name=self.assistant_role_name,
                            user_role_name=self.user_role_name,
                            phase_prompt=self.phase_prompt,
                            phase_name=self.phase_name,
                            assistant_role_prompt=self.assistant_role_prompt,
                            user_role_prompt=self.user_role_prompt,
                            chat_turn_limit=1,  # 只进行一轮对话
                            placeholders=self.phase_env,
                            model_type=self.model_type)
        
        # 4. 更新全局环境
        chat_env = self.update_chat_env(chat_env)
        return chat_env


class RecommendationsForPlacement(Phase):
    """
    【阶段】投放建议 (RecommendationsForPlacement)

    职责：基于市场分析，给出具体的广告投放建议。
    """
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.database_path = "promotion_data.sqlite"

    def update_phase_env(self, chat_env):
        relevant_categories = chat_env.env_dict.get('relevant_categories', [])
        market_data = chat_env.env_dict.get('market_analysis', '')

        # 添加市场数据和相关信息
        self.phase_env.update({
            "task": chat_env.env_dict.get('task_prompt', ''),
            "description": chat_env.env_dict.get('task_description', ''),
            "modality": chat_env.env_dict.get('modality', ''),
            "ideas": chat_env.env_dict.get('ideas', ''),
            "market_analysis": market_data,
            "categories": ', '.join(relevant_categories) if relevant_categories else "无选择的类别"
        })

    def update_chat_env(self, chat_env) -> ChatEnv:
        if len(self.seminar_conclusion) > 0:
            chat_env.env_dict['placement_recommendations'] = self.seminar_conclusion.split("<好的>")[-1].lower().replace(".", "").strip()
        log_visualize(
            "**[投放建议]**:\n\n {}".format(self.seminar_conclusion))
        return chat_env
        
    def execute(self, chat_env, chat_turn_limit=None, need_reflect=None) -> ChatEnv:
        """自定义执行流程，结合原始数据和投放建议"""
        
        # 1. 更新阶段环境
        self.update_phase_env(chat_env)
        
        # 2. 获取市场数据
        market_data = self.phase_env.get("market_analysis", "")
        
        # 投放建议的提示
        if market_data and "未找到相关数据" not in market_data:
            # 有市场数据，基于数据提供建议
            analysis_prompt = self.phase_prompt+"""
基于上面的广告投放数据，请您提供具体的投放建议，包括但不限于：
1. 最佳投放平台选择
2. 合适的投放规模和预算
3. 可参考的投放公司和经验
4. 针对本次任务的定制化投放策略

请注意，您的建议应该是具体且实用的，可以直接用于指导广告投放活动。
不要重复数据内容，而是基于数据给出有针对性的建议。
"""
        else:
            # 没有市场数据，基于任务提供一般性建议
            analysis_prompt = """
您需要提供一份具体的广告投放建议方案，包括但不限于：
1. 最佳投放平台选择
2. 合适的投放规模和预算
3. 针对本次任务的定制化投放策略

请注意，您的建议应该是具体且实用的，可以直接用于指导广告投放活动。
"""
        
        # 更新提示
        self.phase_prompt = analysis_prompt
        
        # 进行对话获取投放建议
        self.seminar_conclusion = \
            self.chatting(chat_env=chat_env,
                        task_prompt=chat_env.env_dict['task_prompt'],
                        need_reflect=need_reflect,
                        assistant_role_name=self.assistant_role_name,
                        user_role_name=self.user_role_name,
                        phase_prompt=analysis_prompt,
                        phase_name=self.phase_name,
                        assistant_role_prompt=self.assistant_role_prompt,
                        user_role_prompt=self.user_role_prompt,
                        chat_turn_limit=chat_turn_limit if chat_turn_limit else 1,
                        placeholders=self.phase_env,
                        model_type=self.model_type)
        
        # 发送到前端
        if self.seminar_conclusion:
            send_msg("投放策略专家", f"根据市场数据分析，以下是针对您任务的投放建议：\n\n{self.seminar_conclusion}")
        
        # 更新全局环境
        chat_env = self.update_chat_env(chat_env)
        return chat_env


class PPTGeneration(Phase):
    """
    【阶段】PPT生成 (PPTGeneration)

    职责：将之前所有阶段的成果汇总，生成一份完整的PPT大纲或内容。
    """
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def update_phase_env(self, chat_env):
        self.phase_env.update({
            "task": chat_env.env_dict['task_prompt'],
            "description": chat_env.env_dict['task_description'],
            "modality": chat_env.env_dict['modality'],
            "ideas": chat_env.env_dict['ideas'],
            "advertising_suggestions": chat_env.env_dict['advertising_suggestions'],
            "placement_recommendations": chat_env.env_dict['placement_recommendations'],
        })

    def update_chat_env(self, chat_env) -> ChatEnv:
        if len(self.seminar_conclusion) > 0:
            chat_env.env_dict['ppt_content'] = self.seminar_conclusion.split("<好的>")[-1].lower().replace(".", "").strip()
        log_visualize(
            "**[PPT Generation Results]**:\n\n {}".format(self.seminar_conclusion))
        return chat_env


class TaskDataClassifier(Phase):
    """
    【阶段】任务数据分类 (TaskDataClassifier)
    
    职责：对输入任务进行分类，判断其所属的行业领域。
    """
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        
        # 修改提示，明确只选择一个类别
        if hasattr(self, 'phase_prompt') and "请您仔细阅读任务目标和类别列表" in self.phase_prompt:
            self.phase_prompt = self.phase_prompt.replace(
                "请您仔细阅读任务目标和类别列表，然后仅回复与当前任务最相关的数据类别名称。",
                "请您仔细阅读任务目标和类别列表，然后仅回复与当前任务最相关的**一个**数据类别名称。请只选择单个最相关类别，不要选择多个。"
            )
    
    def update_phase_env(self, chat_env):
        """更新阶段环境变量"""
        # 获取可用的数据类别
        available_categories = chat_env.env_dict.get("available_categories", [])
        self.phase_env.update({
            "task": chat_env.env_dict.get('task_prompt', ''),
            "available_categories": "\n".join(available_categories)
        })
    
    def update_chat_env(self, chat_env) -> ChatEnv:
        """根据AI选择的类别更新全局环境，只选择最相关的一个类别"""
        # 解析代理回应中的相关类别列表
        if self.seminar_conclusion:
            selected_category = None
            
            # 只取第一个匹配的类别
            for line in self.seminar_conclusion.split('\n'):
                line = line.strip()
                if line and not line.startswith('<') and not line.startswith('#'):
                    # 这可能是一个类别名称
                    if line in chat_env.env_dict.get("available_categories", []):
                        selected_category = line
                        break  # 只取第一个匹配的类别
            
            if selected_category:
                chat_env.env_dict["relevant_categories"] = [selected_category]
                log_visualize(f"**[数据类别分类]**:\n选择了最相关的数据类别: {selected_category}")
                
                # 发送到前端显示
                send_msg("数据工程师", f"根据任务需求，我选择了最相关的数据类别:\n\n- {selected_category}")
            else:
                chat_env.env_dict["relevant_categories"] = []
                log_visualize("**[数据类别分类]**:\n未找到相关类别。")
                send_msg("数据工程师", "分析任务后，未找到相关的数据类别。")
        
        return chat_env
    
    def execute(self, chat_env, max_turns=1, need_reflect=False):
        """执行数据分类阶段"""
        # 首先更新阶段环境
        self.update_phase_env(chat_env)
        
        # 执行代理对话
        self.seminar_conclusion = \
            self.chatting(chat_env=chat_env,
                        task_prompt=chat_env.env_dict['task_prompt'],
                        need_reflect=need_reflect,
                        assistant_role_name=self.assistant_role_name,
                        user_role_name=self.user_role_name,
                        phase_prompt=self.phase_prompt,
                        phase_name=self.phase_name,
                        assistant_role_prompt=self.assistant_role_prompt,
                        user_role_prompt=self.user_role_prompt,
                        chat_turn_limit=max_turns,
                        placeholders=self.phase_env,
                        model_type=self.model_type)
        
        # 更新全局环境
        chat_env = self.update_chat_env(chat_env)
        
        return chat_env